package main

import "fmt"

func main() {
	// 声明slice1为一个切片，并且初始化，默认值为1,2,3，切片长度len为3
	slice1 := []int{1, 2, 3}
	fmt.Printf("len = %d, slice = %v\n", len(slice1), slice1)

	// 声明slice1为一个切片，但是没有给slice分配空间
	var slice2 []int
	//slice2[0] = 1 // 直接赋值，报数组越界错误，因为没有分配空间
	//slice2 = make([]int, 3) // 分配空间，3个int类型元素，每个元素默认值为0
	//slice2[0] = 3
	//slice2[1] = 2
	//slice2[2] = 1
	fmt.Printf("len = %d, slice = %v\n", len(slice2), slice2)

	var slice3 = make([]int, 3)
	slice3[0] = 3
	slice3[1] = 2
	slice3[2] = 1
	fmt.Printf("len = %d, slice = %v\n", len(slice3), slice3)

	// 判断一个slice是否没有分配空间
	if slice2 == nil {
		fmt.Printf("slice2为空切片\n")
	} else {
		fmt.Printf("slice2已分配空间\n")
	}

	// 切片的长度和容量不同，长度表示左指针⾄至右指针之间的距离，容量量表示左指针⾄至底层数组末尾的距离。
	var numbers = make([]int, 3, 5)
	fmt.Printf("切片长度numbers，len = %d, 容量cap = %d, 内容slice = %v\n", len(numbers), cap(numbers), numbers)
	// 向numbers元素追加一个元素1
	numbers = append(numbers, 1)
	fmt.Printf("切片长度numbers，len = %d, 容量cap = %d, 内容slice = %v\n", len(numbers), cap(numbers), numbers)
	numbers = append(numbers, 2)
	// 切片已满，再追加元素时，会追加容量，追加的容量为当前容量的2倍
	numbers = append(numbers, 3)
	numbers = append(numbers, 4)
	numbers = append(numbers, 5)
	numbers = append(numbers, 6)
	numbers = append(numbers, 7)
	numbers = append(numbers, 8)
	fmt.Printf("切片长度numbers，len = %d, 容量cap = %d, 内容slice = %v\n", len(numbers), cap(numbers), numbers)

	// 如果定义时不指定容量大小，那么容量默认为长度大小
	var numbers2 = make([]int, 3)
	fmt.Printf("切片长度numbers2，len = %d, 容量cap = %d, 内容slice = %v\n", len(numbers2), cap(numbers2), numbers2)
	numbers2 = append(numbers2, 1)
	numbers2 = append(numbers2, 2)
	numbers2 = append(numbers2, 3)
	numbers2 = append(numbers2, 4)
	fmt.Printf("切片长度numbers2，len = %d, 容量cap = %d, 内容slice = %v\n", len(numbers2), cap(numbers2), numbers2)

	str := []int{1, 2, 3, 4, 5} // len=3,cap=3
	// s := arr[startIndex:endIndex] 将arr中从下标startIndex到endIndex-1 下的元素创建为一个新的切片
	s1 := str[1:1] //[1,1) ，从第1号位置开始，截取到第1号为准
	s2 := str[:2]  //位置不写，默认从第0个开始
	s3 := str[2:]  //截取值不写，默认截取到最后
	fmt.Printf("切片长度s1，len = %d, 容量cap = %d, 内容slice = %v\n", len(s1), cap(s1), s1)
	fmt.Printf("切片长度s2，len = %d, 容量cap = %d, 内容slice = %v\n", len(s2), cap(s2), s2)
	fmt.Printf("切片长度s3，len = %d, 容量cap = %d, 内容slice = %v\n", len(s3), cap(s3), s3)

	fmt.Println("------------------------------------------------------------")
	fmt.Println("切片截取后均为地址引用，最终指向底层地址是一样的，修改任一值，所有截取数据均发生改变")
	str[1] = 100
	fmt.Println("str=%v", str)
	fmt.Println("s1=%v", s1)
	fmt.Println("s2=%v", s2)

	fmt.Println("------------------------------------------------------------")
	fmt.Println("使用copy深拷贝，来将数组中的值进行拷贝，copy(target, source)")
	var s4 = make([]int, 3)
	copy(str, s4)
	fmt.Printf("s4=%v\n", s4)
	fmt.Printf("str=%v\n", str)
	fmt.Printf("s2=%v\n", s2)
	fmt.Println("深拷贝后，新旧变量指向不同地址，修改任一数组中的值，另一个数组不会跟随修改")
	s4[1] = 100
	fmt.Printf("s4=%v\n", s4)
	fmt.Printf("str=%v\n", str)
}
